package com.iamteer.day14;
/**
主要回顾：线程通信

线程通信：一个线程完成了自己的任务时，要通知另外一个线程去完成另外一个任务

wait();
	等等，如果线程执行了 wait 方法，那么该线程会进入等待状态，等待状态下的线程必须要被其他线程调用 notify 方法才能唤醒

notify();
	唤醒，唤醒等待的线程
	
wait 与 notify 方法的注意事项：
	1. wait 方法与 notify 方法是属于 Object 对象的
	2. wait 方法与 notify 方法必须要在同步代码块或者同步函数中使用
	3. wait 方法与 notify 方法由锁对象调用

 */

//产品类
class Product{
	String name;	//产品名称
	double price;	//产品价格
	boolean flag = false;	//产品是否生产完成
}

class Producer extends Thread{
	Product product;	//
	
	//构造函数：使用同一个产品
	public Producer(Product product){
		this.product = product;
	}
	
	@Override
	public void run() {
		int i = 0;
		while (true) {	//模拟轮番生产苹果和香蕉
			synchronized (product) {	//同步代码块，解决线程安全问题
				if (!product.flag) {	//等消费完再生产		
					if (i%2 == 0) {
						product.name = "Apple";
						product.price = 6.5;
					} else {
						product.name = "Banana";
						product.price = 3.0;
					}
					System.out.println("product: " + product.name + " price: " + product.price);
					i++;
					
					product.flag = true;	//生产完成
					product.notify();		//通知消费者去消费
				}else {
					try {
						product.wait();		//释放锁，等待消费者消费
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}

//消费者类
class Customer extends Thread{
	Product product;	//抽象的产品
	
	//构造函数：为了使用同一个产品
	public Customer(Product product){
		this.product = product;
	}
	
	@Override
	public void run() {
		while (true) {	//模拟产品消费
			synchronized (product) {	//同步代码块，解决线程安全问题
				if (product.flag) {		//要等待生产完成才能消费			
					System.out.println("cunsume: " + product.name + " price: " + product.price);
					product.flag = false;	//消费完了
					product.notify();		//通知生产者生产
				} else {
					try {
						product.wait();		//释放锁，等待产生生产完成
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}

public class ThreadCommunication {

	public static void main(String[] args) {
		Product product = new Product();			//产品对象：注意，指抽象的产品，不是具体的某种
		Producer producer = new Producer(product);	//生产者对象
		Customer customer = new Customer(product);	//消费者对象
		
		producer.start();	//生产者开始生产
		customer.start();	//消费才开始消费
	}

}
